﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using ZhCun.WebCommon.DBModels;
using ZhCun.Utils;

namespace ZhCun.WebCommon.AL
{
    /// <summary>
    /// 数据库日志类型
    /// </summary>
    public enum LogType : byte
    {
        /// <summary>
        /// 用户日志
        /// </summary>
        UserLog = 0,
        /// <summary>
        /// 系统日志
        /// </summary>
        SysLog = 1,
    }

    public class DBLog : BaseAL
    {
        public DBLog()
            : base(DBLogConnString)
        { }

        static DBLog()
        {
            AL = new DBLog();
            Task.Factory.StartNew(LogToDB);
        }
        /// <summary>
        /// 静态当前对象
        /// </summary>
        readonly static DBLog AL;
        /// <summary>
        /// 日志队列
        /// </summary>
        readonly static Queue<TSysLog> LogQueue = new Queue<TSysLog>();
        /// <summary>
        /// http请求日志（webapi和mvc）
        /// </summary>
        readonly static Queue<TSysLogHttp> LogHttpQueue = new Queue<TSysLogHttp>();
        /// <summary>
        /// 日志等待通知
        /// </summary>
        readonly static AutoResetEvent LogWaitNotify = new AutoResetEvent(false);

        static void LogToDB()
        {
            LogHelper.LogObj.Info("数据库日志线程已开启");
            while (true)
            {
                TSysLog log;
                TSysLogHttp httpLog;
                try
                {
                    if (LogQueue.Count > 0)
                    {
                        log = LogQueue.Dequeue();
                        if (log != null)
                        {
                            AL.DB.Insert(log);
                        }
                        Thread.Sleep(50);
                        continue;
                    }

                    if (LogHttpQueue.Count > 0)
                    {
                        httpLog = LogHttpQueue.Dequeue();
                        if (httpLog != null)
                        {
                            if (httpLog.ResponseContent?.Length > 500)                            
                            {
                                httpLog.ResponseContent = httpLog.ResponseContent.Substring(0, 500) + "...";
                            }
                            if (httpLog.RequestContent?.Length > 500)
                            {
                                httpLog.RequestContent = httpLog.RequestContent.Substring(0, 1990) + "...";
                            }
                            AL.DB.Insert(httpLog);
                        }
                        Thread.Sleep(50);
                        continue;
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.LogObj.Error("写数据库日志发生异常", ex);
                }
                LogWaitNotify.WaitOne(1000 * 10);
            }
        }

        public static void WriteLog(TSysLog log)
        {
            //如果 队列加和队列取发生异常，这里应该加上锁
            try
            {
                LogQueue.Enqueue(log);
                LogWaitNotify.Set();
            }
            catch (Exception ex)
            {
                LogHelper.LogObj.Error("日志对象加入队列时发生异常", ex);
            }
        }
        /// <summary>
        /// 写系统日志，只记录日志内容，不保存用户信息
        /// </summary>
        public static void WriteSysLog(string logContent, params object[] args)
        {
            TSysLog log = new TSysLog();
            log.LogType = 1;
            log.LogContent = string.Format(logContent, args);
            WriteLog(log);
        }
        /// <summary>
        /// 写http请求日志
        /// </summary>
        public static void WriteLogHttp(TSysLogHttp log)
        {
            try
            {
                LogHttpQueue.Enqueue(log);
                LogWaitNotify.Set();
            }
            catch (Exception ex)
            {
                LogHelper.LogObj.Error("Http日志对象加入队列时发生异常", ex);
            }
        }
    }
}